package cn.bugstack.springframework.aop.aspectj;

import cn.bugstack.springframework.aop.Pointcut;
import cn.bugstack.springframework.aop.PointcutAdvisor;
import org.aopalliance.aop.Advice;

/**
 * AspectJExpressionPointcutAdvisor类
 * 总之，AspectJExpressionPointcutAdvisor 类封装了一个基于 AspectJ 表达式的切面定义，
 * 其中包括切点、通知和表达式等相关属性，并实现了 PointcutAdvisor 接口，使其能够被 Spring 容器识别为一个切面。
 * 这样就可以在XML文件的配置中定义一个PointcutAdvisor切面拦截器。
 *
 * AspectJExpressionPointcutAdvisor 是 Spring AOP 框架中的一个重要类，用于基于 AspectJ 表达式进行切面配置和通知的织入。
 * 作用：
 *      AspectJExpressionPointcutAdvisor 用于将 AspectJ 表达式与通知（Advice）关联起来，以便在满足特定切点的条件下对目标方法进行拦截和增强。
 * 特点：
 *      支持 AspectJ 表达式：可以使用 AspectJ 的语法来定义切点，从而更灵活地选择目标方法。
 *      与通知关联：可以将各种类型的通知（Advice），如前置通知、后置通知等，与切点表达式关联起来，实现对目标方法的拦截和增强。
 *      与代理工厂结合使用：AspectJExpressionPointcutAdvisor 通常与 Spring 的代理工厂（ProxyFactory）结合使用，通过代理来实现对目标对象的包装和拦截。
 * 主要方法：
 *      setExpression(String expression)：设置 AspectJ 表达式，用于定义切点。
 *      getPointcut()：获取切点对象，包含了切点表达式和类过滤器。
 *      getAdvice()：获取与该切面相关联的通知对象。
 *      setAdvice(Advice advice)：设置通知对象，与切点表达式一起定义了切面的行为。.
 * 使用示例：
 *      AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
 *      advisor.setExpression("execution(* com.example.service.*.*(..))");
 *      advisor.setAdvice(new MethodBeforeAdviceInterceptor(new MyBeforeAdvice()));
 *
 * 在上面的示例中，AspectJExpressionPointcutAdvisor 使用 AspectJ 表达式定义了切点，
 * 表示对 com.example.service 包中所有方法的调用都会触发拦截，然后将前置通知与该切点关联起来。
 *
 * 总的来说，AspectJExpressionPointcutAdvisor 类为 Spring AOP 提供了一种方便的方式来配置切面，
 * 并将通知与切点进行关联，实现对目标方法的拦截和增强。
 * 
 */

public class AspectJExpressionPointcutAdvisor implements PointcutAdvisor {

    // 切点
    private AspectJExpressionPointcut pointcut;
    // 具体的拦截方法
    private Advice advice;
    // 用于存储 AspectJ 表达式。AspectJ 表达式用于定义切入点的匹配规则。
    private String expression;

    public void setExpression(String expression){
        this.expression = expression;
    }

    @Override
    public Pointcut getPointcut() {
        if (null == pointcut) {
            pointcut = new AspectJExpressionPointcut(expression);
        }
        return pointcut;
    }

    @Override
    public Advice getAdvice() {
        return advice;
    }

    public void setAdvice(Advice advice){
        this.advice = advice;
    }

}

